#ifndef _EFFICIENTDET_H_
#define _EFFICIENTDET_H_

#ifdef __cplusplus
extern "C" {
#endif


#include "sample_comm_nnie.h" // 基础HI_类型


/************************************************
 * 网络结构说明: 
 *      位置预测前4个通道为xywh的偏差预测,第5个通道为IoU预测(可选)
 *      类别预测前n个通道是类别预测结果,第n+1个是置信度预测(可选)
*************************************************/
// HI_TRUE/HI_FALSE
#define EFFICIENTDET_PRINT_FLAG (HI_TRUE) // 是否打印耗时信息
// 网络输入图像 宽高
#define EFFICIENTDET_INPUT_WIDTH 640  // w & h
#define EFFICIENTDET_INPUT_HEIGHT 640
#define EFFICIENTDET_PREDICT_IOU (HI_TRUE)  // 预测IOU分支 
#define EFFICIENTDET_PREDICT_CONF (HI_TRUE)  // 预测置信度分支
#define EFFICIENTDET_CLASS_NUM (1) // 类别数
#define EFFICIENTDET_CLASS_THRESHOLD (0.3f) // 置信度阈值,sigmoid后的值
#define EFFICIENTDET_NMS_IOU_THRESHOLD (0.1f) // nms IoU threshold
#define EFFICIENTDET_ANCHOR_INFO {16, 32, 64, 128, 256} // anchor尺寸
// 命令: sudo chown ccc ./*.txt
#define EFFICIENTDET_SAVE_NAME "./efficient/data/result/result_%05d.txt" // 保存的txt名字,需创建好路径,否则会报错
// 不重要的参数
#define EFFICIENTDET_LAYER_NUM (5) // 特征图层数
#define EFFICIENTDET_ANCHOR_NUM (1) // 每个特征点的anchor数
#define EFFICIENTDET_SAVE_MAX_NUM (76*76) // NMS前可存储的目标个数
#define EFFICIENTDET_OUT_MAX_NUM (100) // NMS后可存储的目标个数


typedef struct SVP_SOFT_EfficientDet_S
{
	// ***************       NNIE 计算结果       ***************
	HI_S32* nnie_data_reg[EFFICIENTDET_LAYER_NUM]; // NNIE loc result
	HI_S32* nnie_data_cls[EFFICIENTDET_LAYER_NUM]; // NNIE conf result

	HI_U32 features_w[EFFICIENTDET_LAYER_NUM]; // [80, 40, 20, 10, 5]
	HI_U32 features_h[EFFICIENTDET_LAYER_NUM];
	HI_U32 features_reg_c[EFFICIENTDET_LAYER_NUM]; // [4 (+1)] * 5
	HI_U32 feature_cls_c[EFFICIENTDET_LAYER_NUM]; // [cls_num (+1)] * 5
	HI_U32 feature_stride[EFFICIENTDET_LAYER_NUM]; // align_16(4*w)

	// // ***************       soft 计算结果       ***************
    HI_U8* pu8VirAddr; //分配内存虚拟地址
    HI_U32 u32TotalSize; // 分配内存总大小

	SVP_MEM_INFO_S ps32ResultMem_beforeNMS; // to save [sroce cls x y x y]
	HI_U32 det_num_before_nms; // nms前的检测到的目标数量  (不可>EFFICIENTDET_SAVE_MAX_NUM)

	SVP_MEM_INFO_S is_suppression; // 抑制标志位

	SVP_MEM_INFO_S ps32FinalBbox; // to save [sroce class x y x y]
	HI_U32 final_detection_num; // NMS后检测数量

	// ***************       file       ***************
	FILE *fp_result; // 写bbox结果

	// ***************       pthread       ***************
	HI_BOOL pthread_stop_flag; // 停止线程标志位
	HI_BOOL pthread_busy_flag; // 线程占用标志位

}SVP_SOFT_EfficientDet;


// 线程传递参数
typedef struct EFFICIENT_THREAD_PARA_
{
	SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam; // NNIE信息
	SVP_SOFT_EfficientDet *pstSoftParam; // 软件解码信息
	SAMPLE_SVP_NNIE_PROCESS_SEG_INDEX_S stProcSegIdx; // NNIE处理段id
	SAMPLE_SVP_NNIE_INPUT_DATA_INDEX_S stInputDataIdx; // NNIE输入数据位置

	HI_S32 thread_id; // 线程id
	pthread_mutex_t busy_mutex; // 线程可以工作信号.主函数换醒，并把busy位变1
	pthread_cond_t busy_cond;
}EFFICIENT_THREAD_PARA;

/************************************************
 * EfficientDet运行函数
*************************************************/
// jpg->txt
void EfficientDet_JPG2txt(); // 运行函数
void EfficientDet_JPG2txt_HandleSig(); // 释放内存
// 双NNIE jpg->txt
void EfficientDet_JPG2txt_2NNIE();
void EfficientDet_JPG2txt_2NNIE_HandleSig();


/************************************************
 * EfficientDet底层通用函数
*************************************************/
HI_S32 EfficientDet_NNIE_Forward(SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam, SAMPLE_SVP_NNIE_INPUT_DATA_INDEX_S* pstInputDataIdx,
                                 SAMPLE_SVP_NNIE_PROCESS_SEG_INDEX_S* pstProcSegIdx, HI_BOOL bInstant); // NNIE
HI_S32 EfficientDet_Soft(SAMPLE_SVP_NNIE_PARAM_S *pstDetParam, SVP_SOFT_EfficientDet *pstSoftParam); // Soft
HI_S32 EfficientDet_Soft_ParamInit(SVP_SOFT_EfficientDet *pstSoftParam); // soft初始化


/************************************************
 * ults底层通用函数
*************************************************/
void start_reckon_by_time();
double PCPrintTime(HI_CHAR* str, HI_BOOL print_total_time, HI_BOOL add_total_time, HI_BOOL print_single);
double Efficient_mean_time(int img_num);
HI_S32 Efficient_YUV2BGR(VIDEO_FRAME_INFO_S *pstInput_yuv, SAMPLE_SVP_NNIE_PARAM_S *pstNnieParam, 
						 SAMPLE_SVP_NNIE_INPUT_DATA_INDEX_S* pstInputDataIdx); // yuv -> bgr
HI_S32 Efficient_Read_JPG(FILE *fp_list, HI_U8 *JPGfile_pu8Buf, HI_CHAR cStreamFile[], VDEC_STREAM_S *pstStream, 
						  VDEC_THREAD_PARAM_S stVdecSend[]); // 读取jpg图片->vdec
void Efficient_Soft_Deinit(SVP_SOFT_EfficientDet *pstSoftParam); // soft内存释放


#ifdef __cplusplus
}
#endif

#endif /* _EFFICIENTDET_H_ */
